import {BrowserElement} from "./BrowserElement";
import {IElement} from "./IElement";
import {IXMLDocument} from "./IXMLDocument";
import { NS_STREAM } from "./JSJaCConstants";

export  class BrowserXMLDocument extends BrowserElement implements IXMLDocument {
    private doc:XMLDocument
    private rootElement:IElement
    constructor(xml:string,name:string,namespacesURI:string){
      // parse the string to a new doc
      if(xml) {
        let tempDoc=(new DOMParser()).parseFromString(xml, "text/xml");
        super(tempDoc.documentElement)
        this.doc = tempDoc
        this.rootElement=new BrowserElement(tempDoc.documentElement)
      } else if(name){
        let tempDoc=BrowserXMLDocument.createXMLDocument(name,namespacesURI)
        super(tempDoc.documentElement)
        this.rootElement=new BrowserElement(tempDoc.documentElement)
        this.doc = tempDoc
      } else {
        throw new Error('xml,name paramName all two null is not allowed!!')

      }
    }

   /**
    * 生成XMLDocument对象
    * @param name 
    * @param ns 
    * @returns 
    */
   private static createXMLDocument(name:string,ns:string):XMLDocument{

      let doc:XMLDocument;
      try {
        // DOM2
        if (document.implementation && document.implementation.createDocument) {
          doc = document.implementation.createDocument(ns, name, null);
          // some versions of Moz do not support the readyState property
          // and the onreadystate event so we patch it!
        } else if (window && window.ActiveXObject) {
           doc = new ActiveXObject(BrowserXMLDocument.getPrefix() + ".DomDocument");
        }
        if (!doc.documentElement || doc.documentElement.tagName != name ||
            (doc.documentElement.namespaceURI &&
             doc.documentElement.namespaceURI != ns)) {
              try {
                if (ns !== '')
                  doc.appendChild(doc.createElement(name)).
                    setAttribute('xmlns',ns);
                else
                  doc.appendChild(doc.createElement(name));
              } catch (dex) {
                doc = document.implementation.createDocument(ns,name,null);

                if (doc.documentElement === null)
                  doc.appendChild(doc.createElement(name));

                 // fix buggy opera 8.5x
                if (ns !== '' &&
                    doc.documentElement.getAttribute('xmlns') != ns) {
                  doc.documentElement.setAttribute('xmlns',ns);
                }
              }
            }

        } catch (ex) {
           throw new Error("Your browser does not support XmlDocument objects");
         }
        return doc;
    }



   private static _prefix:string;
   /**
    * 获取符合的XMLDocument的active名称
    */
   private static getPrefix():string {
     if(this._prefix) {
       return this._prefix
     }
     let prefixes:string[] = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
     let o:any;
     for (var i = 0; i < prefixes.length; i++) {
       try {
         // try to create the objects
         o = new ActiveXObject(prefixes[i] + ".DomDocument");
         this._prefix=prefixes[i];
         break;
       }
       catch (ex) {}
     }
     if(this._prefix) {
       return this._prefix;
     }

     throw new Error("Could not find an installed XML parser");


      }

    createElementNS(namespaceURI: string, elementName: string): IElement {
        if(namespaceURI){
           let tempElement=this.doc.createElementNS(namespaceURI,elementName)
           return new BrowserElement(tempElement)
        } else {
            return this.createElement(elementName)
        }

    }
    getRootElement(): IElement {
        return this.rootElement
    }
    createElement(elementName: string): IElement {
        let tempElement=this.doc.createElement(elementName)
        return new BrowserElement(tempElement)
    }
    hasErrorTag(): boolean {
       let errorTag:Element
       if (this.doc.getElementsByTagNameNS) {
           errorTag = this.doc.getElementsByTagNameNS(NS_STREAM, "error").item(0);
       } else {
           let errors = this.doc.getElementsByTagName("error");
           for (let i=0; i<errors.length; i++)
               if (errors.item(i).namespaceURI == NS_STREAM ||
                   errors.item(i).getAttribute('xmlns') == NS_STREAM) {
                   errorTag = errors.item(i);
                   break;
               }
       }
       return errorTag !=null
    }

    clone():IXMLDocument {
       let xmlStr=this.getRootElement().toXmlStr()
       return new BrowserXMLDocument(xmlStr,null,null)

    }
}